package model.net
{
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	
	import model.NetDataParserModel;
	import model.system.TraceManager;

	public class NetSocket extends EventDispatcher
	{
		private static var instance:NetSocket;
		
		internal var socket:Socket;
		
		public function NetSocket()
		{
			if (instance)
			{
				throw Error("单列!");
			}
			initSocket();
		}
		
		public static function getInstance():NetSocket
		{
			if (instance == null)instance = new NetSocket();
			return instance;
		}
		
		private function initSocket():void
		{
			socket = new Socket();
			socket.addEventListener(Event.CONNECT,onConnected);
			socket.addEventListener(Event.CLOSE,onClose);
			socket.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
			socket.addEventListener(ProgressEvent.SOCKET_DATA,onData);
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);
		}
		
		private function onSecurityError(event:SecurityErrorEvent):void
		{
			TraceManager.getInstance().out("security Error!");
		}
		
		private function onData(event:ProgressEvent):void
		{
			//TraceManager.getInstance().out(">>>socket data!");
			parseData();
		}
		
		private function onIOError(event:IOErrorEvent):void
		{
			TraceManager.getInstance().out("socket Error!");
			dispatchEvent(event);
		}
		
		private function onConnected(event:Event):void
		{
			TraceManager.getInstance().out("socket connected!");
			dispatchEvent(event);
		}
		
		private function onClose(event:Event):void
		{
			TraceManager.getInstance().out("socket closed!");
			dispatchEvent(event);
		}
		
		public function connect(ip:String,port:int):void
		{
			socket.connect(ip,port);
		}
		
		public function close():void
		{
			if (socket.connected)
			{
				socket.close();
			}
		}
		
		//解析数据
		
		private var cache:ByteArray = new ByteArray();
		private var data:ByteArray = new ByteArray();
		
		private var cache2:ByteArray = new ByteArray();
		
		private var dataSize:int;
		
		private function parseData():void
		{
			cache.length = 0;

			cache.writeBytes(cache2,0,cache2.bytesAvailable);
			socket.readBytes(cache,cache2.length,socket.bytesAvailable);

			cache2.length = 0;
			cache.position = 0;
			//TraceManager.getInstance().out(cache.length,":cacheLength",cache2.length);
			
			if (cache.length >= 4)
			{
				while(true)
				{
					if (cache.bytesAvailable <= 0)
					{
						break;
					}
					
					dataSize = cache.readUnsignedShort();
					if (cache.bytesAvailable >= dataSize - 2)
					{
						var dataId:int = cache.readShort();
						data.length = 0;
						data.writeBytes(cache,cache.position,dataSize - 4);
						data.position = 0;
						NetDataParserModel.getInstance().excute(dataId,data);
						cache.position = cache.position + dataSize - 4;
						continue;
					}
					else
					{
						cache.position -= 2;
						cache2.writeBytes(cache,cache.position,cache.bytesAvailable);
						break;
					}
				}
			}
			else
			{
				cache2.writeBytes(cache,cache.position,cache.bytesAvailable);
			}
			
			
			cache2.position = 0;
			//TraceManager.getInstance().out(cache.length,":cacheLength2",cache2.length);
		}
	}
}